package com.zyso.service.impl;

import cn.hutool.core.util.URLUtil;
import com.google.common.collect.Lists;
import com.zyso.config.SearchResultCacheConfig;
import com.zyso.pojo.*;
import com.zyso.repository.ZYSoRepository;
import com.zyso.service.ZySoService;
import com.zyso.utils.IpUtils;
import com.zyso.utils.Opslab;
import com.zyso.vo.DetailDdVO;
import com.zyso.vo.DetailVO;
import com.zyso.vo.SearchResultVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.lionsoul.ip2region.xdb.Searcher;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ZySoServiceImpl implements ZySoService {

    @Autowired
    private ZYSoRepository zyRepository;

    @Autowired
    private LinkedHashMap<Integer, Site> sitesResource;

    @Autowired
    private SearchResultCacheConfig searchResultCacheConfig;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Autowired
    private Searcher searcher;

    private static final String VIDEO_FORMAT_M3U8 = "m3u8";

    @Override
    public List<SearchResultVO> searchByWb(String wb, HttpServletRequest request) {
        if (StringUtils.isBlank(wb)) {
            return Collections.emptyList();
        }
        try {
            String ipAddr = IpUtils.getIpAddr(request);
            String region = searcher.search(ipAddr);
            log.info("{} {}", ipAddr, region);
        } catch (Exception e) {
            log.error("", e);
        }
        return searchResultCacheConfig.getSearchResultCache(wb);
    }

    @Override
    public List<SearchResultVO> search(List<Site> sites, String wb) throws InterruptedException {
        //  同步工具
        CountDownLatch countDownLatch = new CountDownLatch(sites.size());
        List<SearchResultVO> list = Lists.newArrayList();
        String encode = URLUtil.encode(wb, StandardCharsets.UTF_8);
        for (Site site : sites) {
            threadPoolExecutor.execute(() -> {
                try {
                    List<SearchResponse> responsesList = zyRepository.search(site.getApi(), encode);
                    if (!CollectionUtils.isEmpty(responsesList)) {
                        for (SearchResponse response : responsesList) {
                            String name = response.getName();
                            if (!StringUtils.contains(name, wb)) {
                                continue;
                            }
                            SearchResultVO vo = new SearchResultVO();
                            BeanUtils.copyProperties(response, vo);
                            vo.setSiteId(site.getId());
                            vo.setSiteName(site.getName());
                            list.add(vo);
                        }
                    }
                } finally {
                    countDownLatch.countDown();
                }
            });
        }
        countDownLatch.await();
        return list;
    }

    @Override
    public DetailVO getDetail(Integer siteId, Integer id) {
        Site site = sitesResource.get(siteId);
        DetailResponse response = zyRepository.detail(site.getApi(), id);
        if (Objects.isNull(response)) {
            return null;
        }
        DetailVO vo = new DetailVO();
        BeanUtils.copyProperties(response, vo);
        DetailDlResponse dl = response.getDl();
        if (Objects.nonNull(dl)) {
            List<DetailDdResponse> m3u8List = dl.getDd().stream().filter(e -> StringUtils.contains(e.getContent(), VIDEO_FORMAT_M3U8)).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(m3u8List)) {
                return null;
            }
            DetailDdResponse ddResponse = m3u8List.stream().findFirst().get();
            String content = ddResponse.getContent();
            if (StringUtils.contains(content, Opslab.HASH)) {
                vo.setDd(Arrays.stream(StringUtils.split(content, Opslab.HASH)).map(e -> transformationDetailDdVO(ddResponse.getFlag(), e)).collect(Collectors.toList()));
            } else {
                vo.setDd(Lists.newArrayList(transformationDetailDdVO(ddResponse.getFlag(), content)));
            }
        }
        return vo;
    }

    private DetailDdVO transformationDetailDdVO(String flag, String content) {
        DetailDdVO vo = new DetailDdVO();
        vo.setFlag(flag);
        vo.setContent(StringUtils.substringBefore(content, Opslab.DOLLAR));
        String link = StringUtils.substringAfter(content, Opslab.DOLLAR);
        vo.setLink(StringUtils.contains(link, Opslab.DOLLAR) ? StringUtils.substringBeforeLast(link, Opslab.DOLLAR) : link);
        return vo;
    }

}
